package com.wayne.client.config;

import org.jasig.cas.client.session.SingleSignOutFilter;
import org.jasig.cas.client.validation.Cas20ProxyTicketValidator;
import org.jasig.cas.client.validation.TicketValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.cas.authentication.CasAuthenticationProvider;
import org.springframework.security.cas.web.CasAuthenticationEntryPoint;
import org.springframework.security.cas.web.CasAuthenticationFilter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;

import javax.annotation.Resource;

/**
 * @author 江南一点雨
 * @微信公众号 江南一点雨
 * @网站 http://www.itboyhub.com
 * @国际站 http://www.javaboy.org
 * @微信 a_java_boy
 * @GitHub https://github.com/lenve
 * @Gitee https://gitee.com/lenve
 */
@Configuration
public class CasSecurityConfig {
  @Resource
  CASClientProperties casClientProperties;
  @Resource
  CASServerProperties casServerProperties;
  @Resource
  UserDetailsService userDetailService;

  @Bean
  ServiceProperties serviceProperties() {
    ServiceProperties serviceProperties = new ServiceProperties();
    serviceProperties.setService(casClientProperties.getLogin());
    return serviceProperties;
  }

  @Bean
  @Primary
  AuthenticationEntryPoint authenticationEntryPoint() {
    // CAS 验证的入口
    CasAuthenticationEntryPoint entryPoint = new CasAuthenticationEntryPoint();
    entryPoint.setLoginUrl(casServerProperties.getLogin());
    entryPoint.setServiceProperties(serviceProperties());
    return entryPoint;
  }

  /**
   * 配置 ticket 校验地址，CAS Client 拿到 ticket 要去 CAS Server 上校验，
   * 默认校验地址是：http://localhost:8443/cas/proxyValidate?ticket=xxx
   * @return
   */
  @Bean
  TicketValidator ticketValidator() {
    return new Cas20ProxyTicketValidator(casServerProperties.getPrefix());
  }

  @Bean
  CasAuthenticationProvider casAuthenticationProvider() {
    CasAuthenticationProvider provider = new CasAuthenticationProvider();
    provider.setServiceProperties(serviceProperties());
    provider.setTicketValidator(ticketValidator());
    provider.setUserDetailsService(userDetailService);
    provider.setKey("javaboy");
    return provider;
  }

  /**
   *  CAS 认证的过滤器，过滤器将请求拦截下来之后，交由 CasAuthenticationProvider 来做具体处理
   * @param authenticationProvider
   * @return
   */
  @Bean
  CasAuthenticationFilter casAuthenticationFilter(AuthenticationProvider authenticationProvider) {
    CasAuthenticationFilter filter = new CasAuthenticationFilter();
    filter.setServiceProperties(serviceProperties());
    filter.setAuthenticationManager(new ProviderManager(authenticationProvider));
    return filter;
  }

  /**
   * 接受 CAS Server 发出的注销请求，
   * 所有的注销请求都将从 CAS Client 转发到 CAS Server，
   * CAS Server 处理完后，会通知所有的 CAS Client 注销登录
   * @return
   */
  @Bean
  SingleSignOutFilter singleSignOutFilter() {
    SingleSignOutFilter sign = new SingleSignOutFilter();
    sign.setIgnoreInitConfiguration(true);
    return sign;
  }

  /**
   * 将注销请求转发到 CAS Server
   * @return
   */
  @Bean
  LogoutFilter logoutFilter() {
    LogoutFilter filter = new LogoutFilter(casServerProperties.getLogout(), new SecurityContextLogoutHandler());
    filter.setFilterProcessesUrl(casClientProperties.getLogoutRelative());
    return filter;
  }
}